home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 October / EnigmA AMIGA RUN 01 (1995)(G.R. Edizioni)(IT)[!][issue 1995-10][Aminet 7].iso / Aminet / dev / gcc / ixemul_src.lha / ixemul-41.0 / library / open.c < prev    next >
C/C++ Source or Header  |  1995-05-28  |  8KB  |  260 lines

  1. /*
  2.  *  This file is part of ixemul.library for the Amiga.
  3.  *  Copyright (C) 1991, 1992  Markus M. Wild
  4.  *  Portions Copyright (C) 1994 Rafael W. Luebbert
  5.  *
  6.  *  This library is free software; you can redistribute it and/or
  7.  *  modify it under the terms of the GNU Library General Public
  8.  *  License as published by the Free Software Foundation; either
  9.  *  version 2 of the License, or (at your option) any later version.
  10.  *
  11.  *  This library is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14.  *  Library General Public License for more details.
  15.  *
  16.  *  You should have received a copy of the GNU Library General Public
  17.  *  License along with this library; if not, write to the Free
  18.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  *
  20.  *  $Id: open.c,v 1.4 1994/06/19 15:14:07 rluebbert Exp $
  21.  *
  22.  *  $Log: open.c,v $
  23.  *  Revision 1.4  1994/06/19  15:14:07  rluebbert
  24.  *  *** empty log message ***
  25.  *
  26.  *  Revision 1.2  1992/07/28  00:32:04  mwild
  27.  *  pass convert_dir the original signal mask, to check for pending signals
  28.  *
  29.  *  Revision 1.1  1992/05/14  19:55:40  mwild
  30.  *  Initial revision
  31.  *
  32.  */
  33.  
  34. #define KERNEL
  35. #include "ixemul.h"
  36. #include "kprintf.h"
  37.  
  38. /* standard functions.. could get overridden in a network environment */
  39. extern int __ioctl (), __fselect (), __close ();
  40.  
  41. /* "normal" functions, means do half-async writes & sync reads */
  42. extern int __write (), __read ();
  43.  
  44. /* sync-write, waits for completion of write, this gets enabled by
  45.  * O_FSYNC */
  46. extern int __sync_write ();
  47.  
  48. extern void __fasync_handler ();
  49.  
  50. /* incore functions */
  51. extern int __mread (), __mclose ();
  52.  
  53. extern int __ioerr_to_errno ();
  54.  
  55.  
  56. int
  57. open (char *name, int mode, int perms)
  58. {
  59.   int fd;
  60.   struct file *f;
  61.   BPTR fh;
  62.   int len, late_stat;
  63.   int omask, error = 0;
  64.   int amode, fnofs;
  65.  
  66.   mode = FFLAGS(mode);
  67.  
  68.   KPRINTF (("open1: write (2,.. %s.\n", write (2, "WR2", 3) == 3 ? "works" : "doesn't work"));
  69.  
  70.   errno = falloc (&f, &fd);
  71.   KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  72.   if (errno != 0) return -1;
  73.   /* we now got the file, ie. since its count is > 0, no other process
  74.    * will get it with falloc() */
  75.  
  76.   KPRINTF (("open2: write (2,.. %s.\n", write (2, "WR2", 3) == 3 ? "works" : "doesn't work"));
  77.  
  78.   KPRINTF (("open3: write (2,.. %s.\n", write (2, "WR2", 3) == 3 ? "works" : "doesn't work"));
  79.   /* init those fields */
  80.   f->f_stb_dirty = 0;
  81.   late_stat = 0;
  82.   if (syscall (SYS_stat, name, &f->f_stb) < 0)
  83.     {
  84.       /* there can mainly be two reasons for stat() to fail. Either the
  85.        * file really doesn't exist (ENOENT), or then the filesystem/handler
  86.        * doesn't support file locks. */
  87.  
  88.       /* if we should get out of here without an error, init the stat
  89.        * buffer after having opened the file with __fstat, this sets some
  90.        * reasonable parameters (see end of function). */
  91.       late_stat = 1;
  92.  
  93. #if 0
  94.       /* GRRR this sounded too good to be true, stat("*") returns
  95.        * ENOENT, so this trick doesn't work */
  96.  
  97.       /* if the file doesn't exist, this is an error if not O_CREAT */
  98.       if ((errno == ENOENT) && !(mode&O_CREAT)) return -1;
  99. #endif
  100.  
  101.       if ((errno == ENOENT) && (mode & O_CREAT))
  102.     {
  103.       /* can't set permissions on an open file, so this has to be done
  104.        * by 'close' */
  105.       f->f_stb.st_mode = perms;
  106.       f->f_stb_dirty = 1;
  107.     }
  108.     }
  109.  
  110.   f->f_flags = mode & FMASK;
  111.  
  112.   KPRINTF (("open4: write (2,.. %s.\n", write (2, "WR2", 3) == 3 ? "works" : "doesn't work"));
  113.   /* initialise the packet. The only thing needed at this time is its
  114.    * header, filling in of port, action & args will be done when it's
  115.    * used */
  116.   __init_std_packet (&f->f_sp);
  117.  
  118.   /* ok, so lets try to open the file... */
  119.  
  120.   /* since we may obtain a filehandle, that wouldn't be closed if we break
  121.    * too early, inhibit signals */
  122.   omask = syscall (SYS_sigsetmask, ~0);
  123.  
  124.   /* do this *only* if the stat() above was successful !! */
  125.   if (!late_stat && S_ISDIR (f->f_stb.st_mode) && !(mode & FWRITE))
  126.     {
  127.       if (convert_dir (f, name, omask) == 0)
  128.         goto ret_ok;
  129.       else
  130.     goto error;
  131.     }
  132.  
  133.   KPRINTF (("open5: write (2,.. %s.\n", write (2, "WR2", 3) == 3 ? "works" : "doesn't work"));
  134.  
  135.   /* filter invalid modes */
  136.   switch (mode & (O_CREAT|O_TRUNC|O_EXCL))
  137.     {
  138.     case O_EXCL:
  139.     case O_EXCL|O_TRUNC:
  140.       /* can never succeed ! */
  141.       error = EINVAL;
  142.       goto error;
  143.  
  144.     case O_CREAT|O_EXCL:
  145.     case O_CREAT|O_EXCL|O_TRUNC:
  146.       if (! late_stat)
  147.         {
  148.       error = EEXIST;
  149.       goto error;
  150.     }
  151.       break;
  152.     }
  153.  
  154.   amode = (mode & O_CREAT) ? MODE_READWRITE : MODE_OLDFILE;
  155.  
  156.   do
  157.   {
  158.     fh = __open (name, amode);
  159.  
  160.     if (! fh)
  161.       {
  162.         int err = IoErr();
  163.  
  164.         /* For those handlers that do not understand MODE_READWRITE (e.g. PAR: ) */
  165.         if (err == ERROR_ACTION_NOT_KNOWN && amode == MODE_READWRITE)
  166.         {
  167.           amode = MODE_NEWFILE;
  168.         }
  169.         else
  170.         {
  171.           error = __ioerr_to_errno (err);
  172.           goto error;
  173.         }
  174.       }
  175.   } while (!fh);
  176.  
  177.   /* now.. we're lucky, we actually opened the file! */
  178.   f->f_fh = (struct FileHandle *) BTOCPTR(fh);
  179.  
  180.   if (mode & FWRITE)
  181.     f->f_write  = (mode & O_FSYNC) ? __sync_write : __write;
  182.   if (mode & FREAD)
  183.     f->f_read   = __read;
  184.  
  185. #if 0
  186.   /* won't work that way, I'll think something up later.. */
  187.  
  188.   /* in this case, we have to setup a handler that is called when ever
  189.    * something arrives at the rw-port, and then walk our filetable and
  190.    * decide whether the packet belonged to a file that has FASYNC set */
  191.   if (mode & FASYNC) signal (__rwport->mp_SigBit, __fasync_handler);
  192. #endif
  193.  
  194.   f->f_ioctl  = __ioctl;
  195.   f->f_select = __fselect;
  196.   f->f_close  = __close;
  197.   f->f_type   = DTYPE_FILE;
  198.  
  199. ret_ok:
  200.   /*
  201.    * have to use kmalloc() instead of malloc(), because this is no task-private
  202.    * data, it could (in the future) be shared by other tasks 
  203.    */
  204.   f->f_name = (void *) kmalloc (strlen (name) + 1);
  205.   strcpy (f->f_name, name);
  206.  
  207.   /* ok, we're almost done. If desired, init the stat buffer to the
  208.    * information we can get from an open file descriptor */
  209.   if (late_stat) __fstat (f);
  210.   
  211.   /* if the file qualifies, try to change it into a DTYPE_MEM file */
  212.   if (!late_stat && f->f_type == DTYPE_FILE 
  213.       && f->f_stb.st_size < ix.ix_membuf_limit && mode == FREAD)
  214.     {
  215.       void *buf;
  216.       
  217.       KPRINTF (("open6: write (2,.. %s.\n", write (2, "WR2", 3) == 3 ? "works" : "doesn't work"));
  218.       /* try to obtain the needed memory */
  219.       buf = (void *) kmalloc (f->f_stb.st_size);
  220.       if (buf)
  221.     if (syscall (SYS_read, fd, buf, f->f_stb.st_size) == f->f_stb.st_size)
  222.       {
  223.         KPRINTF (("open7: write (2,.. %s.\n", write (2, "WR2", 3) == 3 ? "works" : "doesn't work"));
  224.         __Close (CTOBPTR (f->f_fh));
  225.         KPRINTF (("open8: write (2,.. %s.\n", write (2, "WR2", 3) == 3 ? "works" : "doesn't work"));
  226.         f->f_type         = DTYPE_MEM;
  227.         f->f_mf.mf_offset     = 0;
  228.         f->f_mf.mf_buffer     = buf;
  229.         f->f_read        = __mread;
  230.         f->f_close         = __mclose;
  231.         f->f_ioctl        = 0;
  232.         f->f_select        = 0;
  233.       }
  234.     else
  235.       kfree (buf);
  236.     }
  237.  
  238.   syscall (SYS_sigsetmask, omask);
  239.  
  240.   if (error)
  241.     {
  242.       errno = error;
  243.       KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  244.     }
  245.   if (!error && (mode & O_TRUNC) && (amode != MODE_NEWFILE))
  246.     syscall(SYS_ftruncate, fd, 0);
  247.  
  248.   /* return the descriptor */
  249.   return fd;
  250.  
  251. error:
  252.   /* free the file */
  253.   u.u_ofile[fd] = 0;
  254.   f->f_count--;
  255.   syscall (SYS_sigsetmask, omask);
  256.   errno = error;
  257.   KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
  258.   return -1;
  259. }
  260.